AWS Cloud Development Kit (AWS CDK)でECS環境を構築してみた
こんにちは、坂巻です。
AWS上でさくっとコンテナを動かしたくて、AWS Cloud Development Kit (以下、AWS CDK)に辿り着きました。ECSのちょっとした検証でも、ネットワークだったりIAMだったりのリソースも必要で準備に少々時間がかかっていました。
このツールをつかうと、AWSのベストプラクティスに従った設定を内包しており、大部分をよしなにやってくれるようなので今回はこちらを利用して、ECSを構築してみたいと思います。
AWS CDKの詳細については以下をご確認ください。
はじめに
AWS CDKを利用するには、Node.js等の前提ツールが必要になります。本エントリではAWS CDKのセットアップについては割愛していますのでGetting Started with the AWS CDKまたは、以下のブログをご確認ください。
今回は、Fargateを使用してサービスを起動してみたいと思います。
やってみた
AWS CDK初期化
AWS CDKコードを格納するための新しいディレクトリを作成し、AWS CDKを初期化します。今回はTypeScriptを利用します。なお、現在の対応言語はTypeScript、JavaScript、Javaとなります。.NETとPythonについては近々案内があるようです。
$ mkdir MyEcsConstruct $ cd MyEcsConstruct $ cdk init --language typescript
コマンドラインツールキットのインストール
AWS CDKを利用するうえで必須となるツールキットをインストールします。
$ npm install -g aws-cdk
パッケージ追加
今回必要なaws-ec2と、aws-ecsのパッケージを追加します。
$ npm install @aws-cdk/aws-ec2 @aws-cdk/aws-ecs
Fargateサービス作成コード
lib/my_ecs_construct-stack.ts
を編集します。ハイライト部が更新した箇所です。22行名のimage
については、利用したいイメージに置き換えてください。わたしは検証のために、vulnerables/web-dvwaを利用しました。
import cdk = require('@aws-cdk/cdk'); import ec2 = require('@aws-cdk/aws-ec2'); import ecs = require('@aws-cdk/aws-ecs'); export class MyEcsConstructStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc = new ec2.VpcNetwork(this, 'MyVpc', { maxAZs: 2 }); const cluster = new ecs.Cluster(this, 'MyCluster', { vpc: vpc }); // Create a load-balanced Fargate service and make it public new ecs.LoadBalancedFargateService(this, 'MyFargateService', { cluster: cluster, cpu: '256', desiredCount: 1, image: ecs.ContainerImage.fromDockerHub('amazon/amazon-ecs-sample'), memoryMiB: '512', publicLoadBalancer: true }); } }
ビルドします。
$ npm run build
AWS CDK的にはこの時点でスタックが作成されるようなので、スタックの一覧を確認します。
$ cdk ls -l - name: MyEcsConstructStack environment: name: XXXXXXXXXXXX/ap-northeast-1 account: "XXXXXXXXXXXX" region: ap-northeast-1
以下のコマンドでは、実際にデプロイされるCloudFormationテンプレートが確認できます。
$ cdk synth MyEcsConstructStack Resources: MyVpcF9F0CA6F: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsHostnames: true (省略)
AWS上にデプロイします。
$ cdk deploy
AWS CDK内でセキュリティ周り(セキュリティグループやIAM)に変更を加えていると、cdk deploy
実行後に警告が出力されます。確認し問題なければ実行します。
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening). Please confirm you intend to make the following modifications: IAM Statement Changes ┌───┬───────────────────────────────────────────────┬────────┬──────────────────────┬───────────────────────────────────────────────┬───────────┐ │ │ Resource │ Effect │ Action │ Principal │ Condition │ ├───┼───────────────────────────────────────────────┼────────┼──────────────────────┼───────────────────────────────────────────────┼───────────┤ │ + │ ${MyFargateService/Logging/LogGroup.Arn} │ Allow │ logs:CreateLogStream │ AWS:${MyFargateService/TaskDef/ExecutionRole} │ │ │ │ │ │ logs:PutLogEvents │ │ │ ├───┼───────────────────────────────────────────────┼────────┼──────────────────────┼───────────────────────────────────────────────┼───────────┤ ├───┼───────────────────────────────────────────────┼────────┼──────────────────────┼───────────────────────────────────────────────┼───────────┤ │ + │ ${MyFargateService/TaskDef/TaskRole.Arn} │ Allow │ sts:AssumeRole │ Service:ecs-tasks.amazonaws.com │ │ └───┴───────────────────────────────────────────────┴────────┴──────────────────────┴───────────────────────────────────────────────┴───────────┘ Security Group Changes ┌───┬───────────────────────────────────────────────────┬─────┬────────────┬───────────────────────────────────────────────────┐ │ │ Group │ Dir │ Protocol │ Peer │ ├───┼───────────────────────────────────────────────────┼─────┼────────────┼───────────────────────────────────────────────────┤ │ + │ ${MyFargateService/LB/SecurityGroup.GroupId} │ In │ TCP 80 │ Everyone (IPv4) │ │ + │ ${MyFargateService/LB/SecurityGroup.GroupId} │ Out │ TCP 80 │ ${MyFargateService/Service/SecurityGroup.GroupId} │ ├───┼───────────────────────────────────────────────────┼─────┼────────────┼───────────────────────────────────────────────────┤ │ + │ ${MyFargateService/Service/SecurityGroup.GroupId} │ In │ TCP 80 │ ${MyFargateService/LB/SecurityGroup.GroupId} │ │ + │ ${MyFargateService/Service/SecurityGroup.GroupId} │ Out │ Everything │ Everyone (IPv4) │ └───┴───────────────────────────────────────────────────┴─────┴────────────┴───────────────────────────────────────────────────┘ (NOTE: There may be security-related changes not in this list. See http://bit.ly/cdk-2EhF7Np)
実行すると、リソースの作成が開始されます。
Do you wish to deploy these changes (y/n)? y MyEcsConstructStack: deploying... MyEcsConstructStack: creating CloudFormation changeset... 0/39 | 1:26:52 PM | CREATE_IN_PROGRESS | AWS::ECS::Cluster | MyCluster (MyCluster4C1BA579) 0/39 | 1:26:52 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | MyFargateService/TaskDef/TaskRole (MyFargateServiceTaskDefTaskRole62C7D397) 0/39 | 1:26:52 PM | CREATE_IN_PROGRESS | AWS::Logs::LogGroup | MyFargateService/Logging/LogGroup (MyFargateServiceLoggingLogGroup271A17C2) 0/39 | 1:26:52 PM | CREATE_IN_PROGRESS | AWS::ECS::Cluster | MyCluster (MyCluster4C1BA579) Resource creation Initiated 0/39 | 1:26:52 PM | CREATE_IN_PROGRESS | AWS::EC2::EIP | MyVpc/PublicSubnet2/EIP (MyVpcPublicSubnet2EIP8CCBA239) 0/39 | 1:26:52 PM | CREATE_IN_PROGRESS | AWS::EC2::VPC | MyVpc (MyVpcF9F0CA6F) 0/39 | 1:26:53 PM | CREATE_IN_PROGRESS | AWS::EC2::EIP | MyVpc/PublicSubnet1/EIP (MyVpcPublicSubnet1EIP096967CB) 0/39 | 1:26:53 PM | CREATE_IN_PROGRESS | AWS::IAM::Role | MyFargateService/TaskDef/ExecutionRole (MyFargateServiceTa (省略)
マネジメントコンソールを確認すると、CloudFormationのスタックが作成されています。
デプロイ完了を確認後に、ECSを確認するとFargateでサービスが起動されていました。
作成されたALBにアクセスすると、サービスに接続することができました。
削除
以下のコマンドを実行すると、スタック削除が行われます。
$ cdk destroy Are you sure you want to delete: MyEcsConstructStack (y/n)? y MyEcsConstructStack: destroying... 0 | 1:41:46 PM | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | MyEcsConstructStack User Initiated 0 | 1:41:48 PM | DELETE_IN_PROGRESS | AWS::EC2::Route | MyVpc/PrivateSubnet2/DefaultRoute (MyVpcPrivateSubnet2DefaultRoute9CE96294) 0 | 1:41:48 PM | DELETE_IN_PROGRESS | AWS::EC2::Route | MyVpc/PublicSubnet2/DefaultRoute (MyVpcPublicSubnet2DefaultRoute052936F6) (省略) MyEcsConstructStack: destroyed
さいごに
ECSを使用するためには、ネットワーク、IAMの作成など、使用までに多くのステップがあるかと思います。AWS CDKを利用すると、その辺りが内包されていて楽に構築することができました。
少々気になったのが、今回のコードでNATゲートウェイが作成されていました。
マニュアルを確認しましたが、パブリックサブネットにはNATゲートウェイが含まれているようです。
Each Public Subnet will have a NAT Gateway. Each Private Subnet will have a route to the NAT Gateway in the same availability zone.
ベストプラクティスに沿った構成かと思いますが、検証等、一時的な構成の場合は、少々コードをごにょごにょしておかないと、利用料に影響がありそうなので、その辺りは意識が必要かと思います。